//
//  CRInputView.m
//  TestPrj
//
//  Created by 朱铅峰 on 2020/8/3.
//  Copyright © 2020 Xing. All rights reserved.
//

#import "CRInputView.h"
#import "CRHeader.h"
#import <AVFoundation/AVFoundation.h>
#import "CRKeyboardInfoSingleModel.h"
#import "CRInputMoreContainerView.h"
#import "CRInputEmoticonContainerView.h"
#import "NSString+CRKit.h"
#import "CREmoticonManager.h"
#import "CRInputEmoticonDefine.h"
#import "CRKitConfig.h"

@interface CRInputView()<
CRInputEmoticonProtocol,
CRInputToolBarDelegate
>


@end

@implementation CRInputView

@synthesize emoticonContainer = _emoticonContainer;
@synthesize moreContainer = _moreContainer;

- (instancetype)initWithFrame:(CGRect)frame config:(id<CRSessionConfig>)config {
    
    self = [super initWithFrame:frame];
    if (self) {
        self.recording = NO;
        self.recordPhase = CRAudioRecordPhaseEnd;
        self.inputConfig = config;
        self.backgroundColor = [UIColor whiteColor];
    }
    return self;
}

- (void)didMoveToWindow {
    
    [self setUp];
}

- (void)setUp {
    
    self.maxTextLength = 1000;//设置最大输入长度
    
    if (!_toolBar) {
        _toolBar = [[CRInputToolBar alloc] initWithFrame:CGRectMake(0, 0, self.width, 0)];
        [_toolBar setPlaceHolder:@"说点什么吧～"];
    }
    [self addSubview:_toolBar];
    
    // ===== 为toolBar里的按钮绑定事件
    //表情按钮事件
    [self.toolBar.emoticonBtn addTarget:self action:@selector(onTouchEmoticonBtn:) forControlEvents:UIControlEventTouchUpInside];
    //更多按钮事件
    [self.toolBar.moreMediaBtn addTarget:self action:@selector(onTouchMoreBtn:) forControlEvents:UIControlEventTouchUpInside];
    //切换文字录音事件
    [self.toolBar.voiceButton addTarget:self action:@selector(onTouchVoiceBtn:) forControlEvents:UIControlEventTouchUpInside];
    //录音按钮事件
    [self.toolBar.recordButton setTitle:@"按住说话" forState:UIControlStateNormal];
    [self.toolBar.recordButton setHidden:YES];
    [self.toolBar.recordButton addTarget:self action:@selector(onTouchRecordBtnDown:) forControlEvents:UIControlEventTouchDown];
    [self.toolBar.recordButton addTarget:self action:@selector(onTouchRecordBtnDragInside:) forControlEvents:UIControlEventTouchDragInside];
    [self.toolBar.recordButton addTarget:self action:@selector(onTouchRecordBtnDragOutside:) forControlEvents:UIControlEventTouchDragOutside];
    [self.toolBar.recordButton addTarget:self action:@selector(onTouchRecordBtnUpInside:) forControlEvents:UIControlEventTouchUpInside];
    [self.toolBar.recordButton addTarget:self action:@selector(onTouchRecordBtnUpOutside:) forControlEvents:UIControlEventTouchUpOutside];
    //代理
    self.toolBar.delegate = self;
    [self refreshStatus:CRInputStatusText];
    [self sizeToFit];
}

- (CGSize)sizeThatFits:(CGSize)size {
    
    CGFloat toolBarHeight = self.toolBar.height;
    CGFloat containerHeight = 0;
    switch (self.status) {
        case CRInputStatusEmotion:
        {
            containerHeight = self.emoticonContainer.height;
            break;
        }
        case CRInputStatusMore:
        {
            containerHeight = self.moreContainer.height;
            break;
        }
        default:
        {
            UIEdgeInsets safeArea = UIEdgeInsetsZero;
            if (@available(iOS 11.0, *)) {
                safeArea = self.superview.safeAreaInsets;
            }
            NSLog(@"___inpuView.safeArea:%@,superView:%@",NSStringFromUIEdgeInsets(safeArea),self.superview);
            //键盘是从最底下弹起的，需要减去安全区域底部的高度
            CGFloat keyboardDelta = [CRKeyboardInfoSingleModel instance].keyboardHeight - safeArea.bottom;
            
            //如果键盘还没有安全区域高，容器的初始值为0；否则则为键盘和安全区域的高度差值，这样可以保证 toolBar 始终在键盘上面
            containerHeight = keyboardDelta>0 ? keyboardDelta : 0;
        }
           break;
    }
    CGFloat height = toolBarHeight + containerHeight;
    CGFloat width = self.superview? self.superview.width : self.width;
    return CGSizeMake(width, height);
}

- (void)layoutSubviews {
    
    [super layoutSubviews];
    
    self.toolBar.top = 0.f;
    _moreContainer.top     = self.toolBar.bottom;
    _emoticonContainer.top = self.toolBar.bottom;
}

/// 处理高度变化
- (void)callDidChangeHeight {
    
    if (_inputDelegate && [_inputDelegate respondsToSelector:@selector(didChangeInputHeight:)]) {
        if (self.status == CRInputStatusMore ||
            self.status == CRInputStatusEmotion ||
            self.status == CRInputStatusAudio) {
            //这个时候需要一个动画来模拟键盘
            [UIView animateWithDuration:0.25 delay:0 options:7 animations:^{
                [self.inputDelegate didChangeInputHeight:self.height];
            } completion:nil];
        } else {
            [self.inputDelegate didChangeInputHeight:self.height];
        }
    }
}

/// 检测更多面板，没有的话，初始化并加入到输入视图中
- (void)checkMoreContainer {
    
    if (!_moreContainer) {
        CRInputMoreContainerView *moreContainer = [[CRInputMoreContainerView alloc] initWithFrame:CGRectZero];
        moreContainer.size = [moreContainer sizeThatFits:CGSizeMake(self.width, CGFLOAT_MAX)];
        moreContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        moreContainer.hidden   = YES;
        moreContainer.config   = _inputConfig;
        moreContainer.actionDelegate = self.actionDelegate;
        _moreContainer = moreContainer;
    }
    
    //可能是外部主动设置进来的，统一放在这里添加 subview
    if (!_moreContainer.superview) {
        [self addSubview:_moreContainer];
    }
}

/// 检测表情面板，没有的话，初始化并加入到输入视图中
- (void)checkEmoticonContainer {
    
    if (!_emoticonContainer) {
        CRInputEmoticonContainerView *emoticonContainer = [[CRInputEmoticonContainerView alloc] initWithFrame:CGRectMake(0, 0, self.width, 0)];
        emoticonContainer.size = [emoticonContainer sizeThatFits:CGSizeMake(self.width, CGFLOAT_MAX)];
        emoticonContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        emoticonContainer.delegate = self;
        emoticonContainer.hidden = YES;
        emoticonContainer.config = _inputConfig;
        _emoticonContainer = emoticonContainer;
    }
    
    //可能是外部主动设置进来的，统一放在这里添加 subview
    if (!_emoticonContainer.superview) {
        [self addSubview:_emoticonContainer];
    }
}

#pragma mark - getter and setter

- (void)setInputDelegate:(id<CRInputViewDelegate>)inputDelegate {
    
    _inputDelegate = inputDelegate;
}

- (void)setActionDelegate:(id<CRInputActionDelegate>)actionDelegate {
    
    _actionDelegate = actionDelegate;
}

- (CRInputAudioRecordIndicatorView *)audioRecordIndicator {
    
    if (!_audioRecordIndicator) {
        _audioRecordIndicator = [[CRInputAudioRecordIndicatorView alloc] init];
    }
    return _audioRecordIndicator;
}

/// 设置是否录音中
/// @param recording <#recording description#>
- (void)setRecording:(BOOL)recording {
    
    if (recording) {
        self.audioRecordIndicator.center = self.superview.center;
        [self.superview addSubview:self.audioRecordIndicator];
        self.recordPhase = CRAudioRecordPhaseRecording;
    } else {
        [self.audioRecordIndicator removeFromSuperview];
        self.recordPhase = CRAudioRecordPhaseEnd;
    }
    _recording = recording;
}

/// 设置录音状态
/// @param recordPhase <#recordPhase description#>
- (void)setRecordPhase:(CRAudioRecordPhase)recordPhase {
    
    CRAudioRecordPhase prePhase = _recordPhase;
    _recordPhase = recordPhase;
    
    self.audioRecordIndicator.phase = _recordPhase;
    
    if(prePhase == CRAudioRecordPhaseEnd) {
        if (CRAudioRecordPhaseStart == _recordPhase) {
            if ([_actionDelegate respondsToSelector:@selector(onStartRecording)]) {
                [_actionDelegate onStartRecording];
            }
        }
    } else if (prePhase == CRAudioRecordPhaseStart ||
               prePhase == CRAudioRecordPhaseRecording) {
        if (CRAudioRecordPhaseEnd == _recordPhase) {
            if ([_actionDelegate respondsToSelector:@selector(onStopRecording)]) {
                [_actionDelegate onStopRecording];
            }
        }
    } else if (prePhase == CRAudioRecordPhaseCancelling) {
        if (CRAudioRecordPhaseEnd == _recordPhase) {
            if ([_actionDelegate respondsToSelector:@selector(onCancelRecording)]) {
                [_actionDelegate onCancelRecording];
            }
        }
    }
}

/// 设置显示状态
/// @param status 状态
- (void)setStatus:(CRInputStatus)status {
    
    if (_status != status) {
        
        _status = status;
        switch (status) {
            case CRInputStatusEmotion:
                [self checkEmoticonContainer];
                break;
            case CRInputStatusMore:
                [self checkMoreContainer];
                break;
            default:
                break;
        }
    }
}

- (void)setMoreContainer:(UIView *)moreContainer {
    _moreContainer = moreContainer;
    [self sizeToFit];
}

- (void)setEmoticonContainer:(UIView *)emoticonContainer {
    _emoticonContainer = emoticonContainer;
    [self sizeToFit];
}

- (void)setFrame:(CGRect)frame {
    
    CGFloat height = self.frame.size.height;
    [super setFrame:frame];
    if (frame.size.height != height) {
        [self callDidChangeHeight];
    }
}

#pragma mark - 对外方法

/// 刷新输入状态
/// @param status 状态
- (void)refreshStatus:(CRInputStatus)status {
    
    self.status = status;
    
    [self.toolBar updateStatus:status];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.moreContainer.hidden = status != CRInputStatusMore;
        self.emoticonContainer.hidden = status != CRInputStatusEmotion;
    });
}

/// 重置
- (void)reset {
    
    self.width = self.superview.width;
    [self refreshStatus:CRInputStatusText];
    [self sizeToFit];
}

/// 文本框提示语
/// @param placeHolder <#placeHolder description#>
- (void)setInputTextPlaceHolder:(NSString*)placeHolder {
    
    [_toolBar setPlaceHolder:placeHolder];
}

#pragma mark - 按钮事件

- (void)onTouchVoiceBtn:(id)sender {
    
    if (self.status!= CRInputStatusAudio) {
        
        if ([self.actionDelegate respondsToSelector:@selector(onTapVoiceBtn:)]) {
            [self.actionDelegate onTapVoiceBtn:sender];
        }
        __weak typeof(self) weakSelf = self;
        if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)]) {
            [[AVAudioSession sharedInstance] performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
                if (granted) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [weakSelf refreshStatus:CRInputStatusAudio];
                        if (weakSelf.toolBar.showsKeyboard)
                        {
                            weakSelf.toolBar.showsKeyboard = NO;
                        }
                        [weakSelf sizeToFit];
                    });
                }
                else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [Utils showAlertViewWithTitle:@"" content:@"没有麦克风权限" buttonTitle:@"确定" targetVC:[self viewController]];
                    });
                }
            }];
        }
        
    } else {
        
        if ([self.toolBar.inputBarItemTypes containsObject:@(CRInputBarItemTypeTextAndRecord)]) {
            [self refreshStatus:CRInputStatusText];
            self.toolBar.showsKeyboard = YES;
        }
    }
}

- (void)onTouchRecordBtnDown:(id)sender {
    self.recordPhase = CRAudioRecordPhaseStart;
    self.recording = YES;
}
- (void)onTouchRecordBtnUpInside:(id)sender {
    // finish Recording
    self.recordPhase = CRAudioRecordPhaseEnd;
    self.recording = NO;
}
- (void)onTouchRecordBtnUpOutside:(id)sender {
    // cancel Recording
    self.recordPhase = CRAudioRecordPhaseEnd;
    self.recording = NO;
}

- (void)onTouchRecordBtnDragInside:(id)sender {
    // "手指上滑，取消发送"
    self.recordPhase = CRAudioRecordPhaseRecording;
}
- (void)onTouchRecordBtnDragOutside:(id)sender {
    // "松开手指，取消发送"
    self.recordPhase = CRAudioRecordPhaseCancelling;
}

- (void)onTouchEmoticonBtn:(id)sender {
    
    if (self.status != CRInputStatusEmotion) {
        
        if ([self.actionDelegate respondsToSelector:@selector(onTapEmoticonBtn:)]) {
            [self.actionDelegate onTapEmoticonBtn:sender];
        }
        [self checkEmoticonContainer];
        [self bringSubviewToFront:self.emoticonContainer];
        [self.emoticonContainer setHidden:NO];
        [self.moreContainer setHidden:YES];
        [self refreshStatus:CRInputStatusEmotion];
        [self sizeToFit];
        
        if (self.toolBar.showsKeyboard) {
            self.toolBar.showsKeyboard = NO;
        }
        
    } else {
        
        [self refreshStatus:CRInputStatusText];
        self.toolBar.showsKeyboard = YES;
    }
}

- (void)onTouchMoreBtn:(id)sender {
    
    if (self.status != CRInputStatusMore) {
        
        if ([self.actionDelegate respondsToSelector:@selector(onTapMoreBtn:)]) {
            [self.actionDelegate onTapMoreBtn:sender];
        }
        [self checkMoreContainer];
        [self bringSubviewToFront:self.moreContainer];
        [self.moreContainer setHidden:NO];
        [self.emoticonContainer setHidden:YES];
        [self refreshStatus:CRInputStatusMore];
        [self sizeToFit];

        if (self.toolBar.showsKeyboard) {
            self.toolBar.showsKeyboard = NO;
        }
        
    } else {
        
        [self refreshStatus:CRInputStatusText];
        self.toolBar.showsKeyboard = YES;
    }
}

- (BOOL)endEditing:(BOOL)force {
    
    BOOL endEditing = [super endEditing:force];
    
    if (!self.toolBar.showsKeyboard) {
        
        UIViewAnimationCurve curve = UIViewAnimationCurveEaseInOut;
        
        __weak typeof(self) weakSelf = self;
        void(^animations)(void) = ^{
            [weakSelf refreshStatus:CRInputStatusText];
            [weakSelf sizeToFit];
            if (weakSelf.inputDelegate && [weakSelf.inputDelegate respondsToSelector:@selector(didChangeInputHeight:)]) {
                [weakSelf.inputDelegate didChangeInputHeight:weakSelf.height];
            }
        };
        NSTimeInterval duration = 0.25;
        [UIView animateWithDuration:duration delay:0.0f options:(curve << 16 | UIViewAnimationOptionBeginFromCurrentState) animations:animations completion:nil];
    }
    return endEditing;
}


#pragma mark - 表情页面代理 CRInputEmoticonProtocol

- (void)emoticonDidPressSend:(id)sender {
    
    if ([self.actionDelegate respondsToSelector:@selector(onSendText:atUsers:)] && [self.toolBar.contentText length] > 0) {
        NSString *sendText = self.toolBar.contentText;
        [self.actionDelegate onSendText:sendText atUsers:@[]];//self.atCache allAtUid:sendText
        //[self.atCache clean];
        self.toolBar.contentText = @"";
        [self.toolBar layoutIfNeeded];
    }
}

- (void)selectedEmoticon:(NSString*)emoticonID catalog:(NSString*)emotCatalogID description:(NSString *)description {
    
    if (!emotCatalogID) { //删除键
        [self doButtonDeleteText];
    }else{
        if ([emotCatalogID isEqualToString:CRKit_EmojiCatalog]) {
            [self.toolBar insertText:description];
        }else{
            //发送贴图消息
            if ([self.actionDelegate respondsToSelector:@selector(onSelectChartlet:catalog:)]) {
                [self.actionDelegate onSelectChartlet:emoticonID catalog:emotCatalogID];
            }
        }
    }
}

#pragma mark - 输入栏代理及相关方法

- (BOOL)textViewShouldBeginEditing {
    
    [self refreshStatus:CRInputStatusText];
    return YES;
}

- (BOOL)shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    
    if ([text isEqualToString:@"\n"]) {
        [self emoticonDidPressSend:nil];
        return NO;
    }
  
    if ([text isEqualToString:@""] && range.length == 1) {
        //非选择删除
        return [self onTextDelete];
    }

//    if ([self shouldCheckAt]) {
//        // @ 功能
//        [self checkAt:text];
//    }
    
    NSString *str = [self.toolBar.contentText stringByAppendingString:text];
    if (str.length > self.maxTextLength) {
        return NO;
    }
    return YES;
}

- (void)textViewDidChange {
    
    if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(onTextChanged:)]) {
        
        [self.actionDelegate onTextChanged:self];
    }
}

- (void)toolBarDidChangeHeight:(CGFloat)height {
    
    [self sizeToFit];
}

//- (BOOL)shouldCheckAt {
//
//    BOOL disable = NO;
//    if ([self.inputConfig respondsToSelector:@selector(disableAt)]) {
//        disable = [self.inputConfig disableAt];
//    }
//    return !disable;
//}
//
//- (void)checkAt:(NSString *)text {
//
//    if ([text isEqualToString:CRInputAtStartChar]) {
//        switch (self.session.sessionType)
//        {
//            case NIMSessionTypeTeam:
//            {
//                NIMContactTeamMemberSelectConfig *config = [[NIMContactTeamMemberSelectConfig alloc] init];
//                config.teamType = NIMKitTeamTypeNomal;
//                config.needMutiSelected = NO;
//                config.teamId = self.session.sessionId;
//                config.session = self.session;
//                config.filterIds = @[[NIMSDK sharedSDK].loginManager.currentAccount];
//                NIMContactSelectViewController *vc = [[NIMContactSelectViewController alloc] initWithConfig:config];
//                vc.delegate = self;
//                dispatch_async(dispatch_get_main_queue(), ^{
//                    [vc show];
//                });
//            }
//                break;
//            case NIMSessionTypeSuperTeam:
//            {
//                NIMContactTeamMemberSelectConfig *config = [[NIMContactTeamMemberSelectConfig alloc] init];
//                config.teamType = NIMKitTeamTypeSuper;
//                config.needMutiSelected = NO;
//                config.teamId = self.session.sessionId;
//                config.session = self.session;
//                config.filterIds = @[[NIMSDK sharedSDK].loginManager.currentAccount];
//                NIMContactSelectViewController *vc = [[NIMContactSelectViewController alloc] initWithConfig:config];
//                vc.delegate = self;
//                dispatch_async(dispatch_get_main_queue(), ^{
//                    [vc show];
//                });
//            }
//                break;
//            case NIMSessionTypeP2P:
//                break;
//            case NIMSessionTypeChatroom:
//                break;
//            default:
//                break;
//        }
//    }
//}

- (BOOL)onTextDelete {

    NSRange range = [self delRangeForEmoticon];
//    if (range.length == 1) {
//        //删的不是表情，可能是@
//        NIMInputAtItem *item = [self delRangeForAt];
//        if (item) {
//            range = item.range;
//        }
//    }
    if (range.length == 1) {
        //自动删除
        return YES;
    }
    [self.toolBar deleteText:range];
    return NO;
}

- (BOOL)doButtonDeleteText {

    NSRange range = [self delRangeForLastComponent];
//    if (range.length == 1)
//    {
//        //删的不是表情，可能是@
//        NIMInputAtItem *item = [self delRangeForAt];
//        if (item) {
//            range = item.range;
//        }
//    }

    [self.toolBar deleteText:range];
    return NO;
}

- (NSRange)delRangeForEmoticon {

    NSString *text = self.toolBar.contentText;
    NSRange selectedRange = [self.toolBar selectedRange];
    BOOL isEmoji = NO;
    if (selectedRange.location >= 2) {
        NSString *subStr = [text substringWithRange:NSMakeRange(selectedRange.location - 2, 2)];
        isEmoji = [subStr cr_containsEmoji];
    }

    NSRange range = NSMakeRange(selectedRange.location - 1, 1);
    if (isEmoji) {
        range = NSMakeRange(selectedRange.location-2, 2);
    } else {
        NSRange subRange = [self rangeForPrefix:@"[" suffix:@"]"];
        if (subRange.length > 1)
        {
            NSString *name = [text substringWithRange:subRange];
            CRInputEmoticon *icon = [[CRInputEmoticonManager sharedManager] emoticonByTag:name];
            range = icon? subRange : NSMakeRange(selectedRange.location - 1, 1);
        }
    }

    return range;
}

- (NSRange)delRangeForLastComponent {

    NSString *text = self.toolBar.contentText;
    NSRange selectedRange = [self.toolBar selectedRange];
    if (selectedRange.location == 0) {
        return NSMakeRange(0, 0) ;
    }

    NSRange range;
    NSRange subRange = [self rangeForPrefix:@"[" suffix:@"]"];

    if (text.length > 0 &&
        [[text substringFromIndex:text.length - 1] isEqualToString:@"]"] &&
        subRange.length > 1) {

        NSString *name = [text substringWithRange:subRange];
        CRInputEmoticon *icon = [[CRInputEmoticonManager sharedManager] emoticonByTag:name];
        range = icon? subRange : NSMakeRange(selectedRange.location - 1, 1);

    } else {

        range = [text cr_rangeOfLastUnicode];
    }

    return range;
}


//- (NIMInputAtItem *)delRangeForAt {
//
//    NSString *text = self.toolBar.contentText;
//    NSRange range = [self rangeForPrefix:NIMInputAtStartChar suffix:NIMInputAtEndChar];
//    NSRange selectedRange = [self.toolBar selectedRange];
//    NIMInputAtItem *item = nil;
//    if (range.length > 1)
//    {
//        NSString *name = [text substringWithRange:range];
//        NSString *set = [NIMInputAtStartChar stringByAppendingString:NIMInputAtEndChar];
//        name = [name stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:set]];
//        item = [self.atCache item:name];
//        range = item? range : NSMakeRange(selectedRange.location - 1, 1);
//    }
//    item.range = range;
//    return item;
//}


- (NSRange)rangeForPrefix:(NSString *)prefix suffix:(NSString *)suffix {

    NSString *text = self.toolBar.contentText;
    NSRange range = [self.toolBar selectedRange];
    NSString *selectedText = range.length ? [text substringWithRange:range] : text;
    NSInteger endLocation = range.location;
    if (endLocation <= 0) {
        return NSMakeRange(NSNotFound, 0);
    }
    NSInteger index = -1;
    if ([selectedText hasSuffix:suffix]) {
        //往前搜最多20个字符，一般来讲是够了...
        NSInteger p = 20;
        for (NSInteger i = endLocation; i >= endLocation - p && i-1 >= 0 ; i--)
        {
            NSRange subRange = NSMakeRange(i - 1, 1);
            NSString *subString = [text substringWithRange:subRange];
            if ([subString compare:prefix] == NSOrderedSame)
            {
                index = i - 1;
                break;
            }
        }
    }
    return index == -1? NSMakeRange(endLocation - 1, 1) : NSMakeRange(index, endLocation - index);
}

@end
